#pragma once

/*------------------------------------------------------------------------
  Exception
  ------------------------------------------------------------------------*/

class Exception
{
public:
    virtual DWORD GetErrorCode() const = 0;
    virtual DWORD GetSubErrorCode() const = 0;
    virtual DWORD GetErrorParam() const = 0;
    virtual wchar_t * GetErrorMessage() const = 0;
};

/*-----------------------------------------------------------------------
  GenericException
  -----------------------------------------------------------------------*/

class GenericException : public Exception
{
public:

    GenericException() 
    : m_errorCode(GetLastError()), m_subError(-1), m_errorParam(-1) 
    { }
    GenericException(DWORD errorCode) 
    : m_errorCode(errorCode), m_subError(-1), m_errorParam(-1) 
    { }
    GenericException(DWORD errorCode, DWORD subError, DWORD errorParam) 
    : m_errorCode(errorCode), m_subError(subError), m_errorParam(errorParam)
    { m_subError = subError; m_errorParam = errorParam; }
    
    DWORD GetErrorCode() const { return m_errorCode; }
    DWORD GetSubErrorCode() const { return m_subError; }
    DWORD GetErrorParam() const { return m_errorParam; }
    
    wchar_t * GetErrorMessage() const { return 0; }

private:

    static const CaptureStackSize = 8;
    DWORD m_errorCode;
    DWORD m_subError;
    DWORD m_errorParam;    
};



// The base Exception class for all exceptions generated by stress code
class ApplicationException : public GenericException
{
public:

    ApplicationException() 
    : GenericException(GetLastError(), -1, -1) 
    { }
    ApplicationException(DWORD errorCode) 
    : GenericException(errorCode)
    { }
    ApplicationException(DWORD errorCode, DWORD subError, DWORD errorParam) 
    : GenericException(errorCode, subError, errorParam)
    { }	
};

#define DECLARE_STRESS_EXCEPTION(CLASS,CODE) \
class CLASS : public ApplicationException \
{  public: CLASS() : ApplicationException(CODE) {} };

DECLARE_STRESS_EXCEPTION( OutOfMemoryException, ERROR_OUTOFMEMORY )
DECLARE_STRESS_EXCEPTION( DataCorruptionException, ERROR_FILE_CORRUPT )
DECLARE_STRESS_EXCEPTION( UnexpectedEOFException, ERROR_HANDLE_EOF )
DECLARE_STRESS_EXCEPTION( InvalidDataException, ERROR_INVALID_DATA )
DECLARE_STRESS_EXCEPTION( InvalidParameterException, ERROR_INVALID_PARAMETER )
DECLARE_STRESS_EXCEPTION( NotSupportedException, ERROR_NOT_SUPPORTED )
DECLARE_STRESS_EXCEPTION( InvalidStateException, ERROR_INVALID_STATE);

class ComException : public ApplicationException
{
    HRESULT m_hr;

public:

    ComException( HRESULT errorCode ) : m_hr(errorCode) {}
    HRESULT GetHR() const { return m_hr;}
};

class UndefinedException : public ApplicationException
{
public:
    UndefinedException() : ApplicationException(0) {}
};

